﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Skymate.Lyjt.Tests
{
    using Abp.Modules;
    using Abp.TestBase;

    using Castle.MicroKernel.Registration;

    using Shouldly;

    using Skymate.Lyjt.Core;

    using Xunit;

    [TestClass]
    public class UnitTest1: TestBase
    {
        [TestMethod]
        public void DateTest()
        {
            var date = new DateTime(1970, 1, 2, 0, 0, 0, 0);
            var start = new DateTime(1970, 1, 1, 0, 0, 0, 0);
            var ms = date - start;

            ms.TotalSeconds.ShouldBe(86400);
            BitConverter.GetBytes((int)ms.TotalSeconds).ShouldBe(new byte[] { 0x80, 0x51, 0x01, 0x00 });
            
        }

        [TestMethod]
        public void GetReadBufferCheckSumTest()
        {
            var data =new byte[] {0xC0,0x01,0x02,0x0c,0xC0};
            this.GetReadBufferCheckSumTest(data,0x0c);

            var data1= new byte[] { 0xC0, 0x01, 0x02, 0x0c, 0x45,0x00,0xC0 };

            this.GetReadBufferCheckSumTest(data1, 0x00);

            var data2 = new byte[] { 0xC0, 0x01, 0x02, 0x0c, 0xDB, 0xDD, 0xC0 };
            this.GetReadBufferCheckSumTest(data2, 0xDB);

            var data3 = new byte[] { 0xC0, 0x01, 0x02, 0x0c, 0xDB, 0xDC, 0xC0 };
            this.GetReadBufferCheckSumTest(data3, 0xC0);

            var data4 = new byte[] { 0xC0, 0x01, 0x02, 0x0c, 0xDB, 0xDA, 0xC0 };
            this.GetReadBufferCheckSumTest(data4, 0x41);

        }

        [TestMethod]
        public void GetReadDataLengthTest()
        {
            var data = new byte[] { 0xC0, 0x01, 0x02, 0x0c, 0xC0 };
            this.GetReadDataLengthTest(data, 2);

            var data1 = new byte[] { 0xC0, 0x01, 0x02, 0x0c, 0x45, 0x00, 0xC0 };

            this.GetReadDataLengthTest(data1, 4);

            var data2 = new byte[] { 0xC0, 0x01, 0x02, 0x0c, 0xDB, 0xDD, 0xC0 };
            this.GetReadDataLengthTest(data2, 3);

            var data3 = new byte[] { 0xC0, 0x01, 0x02, 0x0c, 0xDB, 0xDC, 0xC0 };
            this.GetReadDataLengthTest(data3, 3);

            var data4 = new byte[] { 0xC0, 0x01, 0x02, 0x0c, 0xDB, 0xDA, 0xC0 };
            this.GetReadDataLengthTest(data4, 3);

        }

        [TestMethod]
        public void GenerateChecksumTest()
        {
            GenerateChecksumTest(
                new byte[] {0x01},0x01 );
            GenerateChecksumTest(
                new byte[] { 0x01,0x02 }, 0x03);
            GenerateChecksumTest(
                new byte[] { 0x01, 0x02,0x03 }, 0x06);

            GenerateChecksumTest(
                new byte[] { 0xFF, 0xFE, 0xA0 }, 0x9D);

            GenerateChecksumTest(
                new byte[] { 0xBF, 0x01}, 0xC0);
            GenerateChecksumTest(
                new byte[] { 0xD9, 0x01, 0x01 }, 0xDB);


        }

        [TestMethod]
        public void CheckSumIsRightTest()
        {
            CheckSumIsRightTest(
                new byte[] { 0x01 }, 0x01,true);
            CheckSumIsRightTest(
                new byte[] { 0x01, 0x02 }, 0x03, true);
            CheckSumIsRightTest(
                new byte[] { 0x01, 0x02, 0x03 }, 0x06, true);

            CheckSumIsRightTest(
                new byte[] { 0xFF, 0xFE, 0xA0 }, 0x9D, true);

            CheckSumIsRightTest(
                new byte[] { 0xBF, 0x01 }, 0xC0, true);

            CheckSumIsRightTest(
                new byte[] { 0xD9, 0x01, 0x01 }, 0xDB, true);
            
            CheckSumIsRightTest(
                new byte[] { 0xFF, 0xFE, 0xA0 }, 0x9E, false);

            CheckSumIsRightTest(
                new byte[] { 0xBF, 0x01 }, 0xC1, false);

        }

        [TestMethod]
        public void DecryptDataTest()
        {
            DecryptDataTest(
                new byte[]{0x01,0x02},
                new byte[] { 0x01, 0x02 });

            DecryptDataTest(
                new byte[] { 0xDB, 0xDD },
                new byte[] { 0xDB });

            DecryptDataTest(
                new byte[] { 0xDB, 0xDC },
                new byte[] { 0xC0 });

            DecryptDataTest(
                new byte[] { 0xDB, 0xDA },
                new byte[] { 0x41 });

            DecryptDataTest(
                new byte[] { 0x01,0x02,0x04,0xDB, 0xDC,0xA0,0xA2,0xA2 },
                new byte[] { 0x01, 0x02, 0x04, 0xC0, 0xA0, 0xA2, 0xA2 });

            DecryptDataTest(
                new byte[]
                    {
                        0x01, 0x02, 0x04, 0xDB, 0xDC, 0xA0, 0xA2, 0xA2,
                        0xDB, 0xDD,0xC0, 0xC2, 0xC2
                    },
                new byte[] { 0x01, 0x02, 0x04, 0xC0, 0xA0, 0xA2, 0xA2,
                        0xDB, 0xC0, 0xC2, 0xC2 });


        }

        [TestMethod]
        public void ReadTest()
        {
            ReadTest(
                new byte[] {0xC0,0xDB,0xDA, 0x01, 0x02, 0xB8,0xC0},
                new byte[] {0x41,0x01,0x02});

            ReadTest(
                new byte[] { 0xC0, 0x01,  0x01, 0xC0 },
                new byte[] { 0x01 });

            ReadTest(
                new byte[] { 0xC0, 0x01, 0x00, 0xC0 },
                new byte[] {  });

            ReadTest(
                new byte[] { 0xC0, 0xDB, 0xDD, 0xB8, 0xC0 },
                new byte[] { 0xDB });


            ReadTest(
                new byte[] { 0xC0, 0xDB, 0xDC, 0xB7, 0xC0 },
                new byte[] { 0xC0 });

        }
        
        [Theory]
        [InlineData(new byte[] { 0xD9, 0x02 },new byte[]                  {0xC0,0xD9,0x02,0xDB,0xDD,0xC0})]
        [InlineData(new byte[] { 0xBF, 0x01 }, new byte[] { 0xC0,0xBF,0x01,0xDB,0xDC,0xC0
 })]
        [InlineData(new byte[] { 0xDB }, new byte[] { 0xC0, 0xDB, 0xDD, 0xB8, 0xC0 })]
        [InlineData(new byte[] { 0xC0 }, new byte[] { 0xC0, 0xDB, 0xDC, 0xB7, 0xC0 })]
        [InlineData(new byte[] { 0x01, 0xA1 }, new byte[] { 0xC0, 0x01, 0xA1, 0xA2, 0xC0 })]
        [InlineData(new byte[] { 0x41, 0xA1 }, 
                    new byte[] { 0xC0, 0xDB,0xDA, 0xA1, 0x56, 0xC0 })]
        public void EncryDataTest(byte[] datas,byte[] encry)
        {
            var analysisTool = this.AbpBootstrapper.IocManager.Resolve<IProtocolAnalysis>();
            var databuffer = analysisTool.EncryData(datas);

            databuffer.ShouldBe(encry);

        }

        private void ReadTest(byte[] 
            buffer,byte[] datas)
        {
            var analysisTool = this.AbpBootstrapper.IocManager.Resolve<IProtocolAnalysis>();
            var databuffer = analysisTool.Read(buffer);

            databuffer.ShouldBe(datas);

        }


        private void DecryptDataTest(byte[] databuffer,byte[] assert)
        {
            var analysisTool = this.AbpBootstrapper.IocManager.Resolve<IProtocolAnalysis>();
            var buffer = analysisTool.DecryptData(databuffer);

            buffer.ShouldBe(assert);

        }

        private void CheckSumIsRightTest(
            byte[] datas,byte checksum, bool right)
        {
            var analysisTool = this.AbpBootstrapper.IocManager.Resolve<IProtocolAnalysis>();

            var isRight = analysisTool.CheckSumIsRight(datas, checksum);
            isRight.ShouldBe(right);

        }

        private void GenerateChecksumTest(byte[] datas,byte checkSum)
        {
            var analysisTool = this.AbpBootstrapper.IocManager.Resolve<IProtocolAnalysis>();

            var gCheckSum = analysisTool.GenerateChecksum(datas);
            gCheckSum.ShouldBe(checkSum);

        }


        private void GetReadDataLengthTest(byte[] datas, int length)
        {
            var analysisTool = this.AbpBootstrapper.IocManager.Resolve<IProtocolAnalysis>();
            int readLength = analysisTool.GetReadDataLength(datas);
            readLength.ShouldBe(length);
        }

        private void GetReadBufferCheckSumTest(
            byte[] datas,byte check)
        {
            var analysisTool = this.AbpBootstrapper.IocManager.Resolve<IProtocolAnalysis>();
            byte readCheck = analysisTool.GetReadBufferCheckSum(datas);
            readCheck.ShouldBe((byte)check);
        }
    }

    public class TestBase:AbpIntegratedTestBase<TestModule>
    {

    }

    [DependsOn(typeof(LyjtCoreModule))]
    public class TestModule : AbpTestBaseModule
    {

    }
}
